#include <cassert>
#include <thread>
#include <iostream>
#include <unistd.h>
#include "processor.hpp"
#include "macro.hpp"

namespace jizhe {

/// 全局静态变量，用于生成调度器id
static std::atomic<uint64_t> s_proc_id{0};
/// 全局静态变量，用于统计当前的调度器数
static std::atomic<uint64_t> s_proc_count{0};

/// 当前线程的调度器，每个线程独有
static thread_local Processor* t_proc;

void Processor::schedule(Processor::Task* task) {
    t_proc->m_local_que.push(task);
}

void Processor::schedule(std::function<void()> func) {
    LOG_CO("t_proc: " << t_proc);
    Task* task = new Task(func);
    t_proc->m_local_que.push(task);
}

void Processor::schedule(Coroutine co) {
    Task* task = new Task(co.shared_from_this());
    t_proc->m_local_que.push(task);
}

Processor::Processor() {
    ConQueue<Task*> m_local_que();
    m_id = s_proc_id;
    ++s_proc_id;
    ++s_proc_count;
    LOG_CO("Create Processor id=" << m_id);
}

// Processor::~Processor() {
//     --s_proc_count;
// }

void Processor::run() {
    //assert(t_running_co == nullptr && t_schedule_co == nullptr);
    LOG_CO("Processor id=" << m_id << " start running");
    t_proc = this;
    m_co = Coroutine::GetThis();
    Task* task = new Task();
    // 用于实际执行任务的协程,可复用防止频繁创建
    Coroutine::ptr worker; 
    while(true) {
        task->reset();
        auto opt = m_local_que.try_pop();
        
        if (opt != std::nullopt) {
            task = opt.value();
            if (task->task_func) {
                if (worker) {
                    worker->reset(task->task_func);            
                } else {
                    worker.reset(new Coroutine(task->task_func));
                }
                worker->resume();
                worker.reset();
            } else if(task->task_co) {
                task->task_co->resume();
            }
        } else {
            // 本地任务队列为空
            // jizhe::Coroutine::GetThis()->yield();
            sleep(5);
            LOG_CO("sleep 5s");
        }

    }
}

void Processor::addTask(Processor::Task* task) {
    m_local_que.push(task);
}

void Processor::addTask(std::function<void()> func) {
    Task* task = new Task(func);
    m_local_que.push(task);
}

void Processor::addTask(Coroutine co) {
    Task* task = new Task(co.shared_from_this());
    m_local_que.push(task);
}

}